import * as DocumentPicker from "expo-document-picker";
import * as FileSystem from "expo-file-system";
import * as ImagePicker from "expo-image-picker";
import * as Linking from "expo-linking";
import * as MediaLibrary from "expo-media-library";
import * as Speech from "expo-speech";

import {
  Alert,
  Button,
  FlatList,
  PermissionsAndroid,
  Platform,
  ScrollView,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from "react-native";
import React, { useRef, useState } from "react";

import { Audio } from "expo-av";
import { BlurView } from "expo-blur";
import { useNavigation } from "@react-navigation/native";

export default function TabOneScreen() {
  const navigation = useNavigation();
  const [loading, setLoading] = useState(false);
  const [text, setText] = useState("");
  const [recording, setRecording] = useState(null);
  const [recordedUri, setRecordedUri] = useState("");
  const [isRecording, setIsRecording] = useState(false);
  const [recordings, setRecordings] = useState([]);
  const [editingName, setEditingName] = useState({ uri: "", name: "" });
  const [isEditing, setIsEditing] = useState(false);
  const [saveDirectory, setSaveDirectory] = useState(
    FileSystem.documentDirectory
  );
  const singleTapRef = useRef(null);
  const startPressTimeRef = useRef(0);

  const requestMediaLibraryPermissions = async () => {
    const { status } = await MediaLibrary.requestPermissionsAsync();
    if (status !== "granted") {
      alert("Permission to access media library is required!");
      return false;
    }
    return true;
  };

  const startRecording = async () => {
    startPressTimeRef.current = Date.now(); // 记录按下开始录音的时间

    try {
      const { status } = await Audio.requestPermissionsAsync();
      if (status !== "granted") {
        alert("Permission to access microphone is required!");
        return;
      }

      if (!saveDirectory) {
        alert(
          "保存目录不存在，Please select a directory to save the recording."
        );
        return;
      }

      await Audio.setAudioModeAsync({
        allowsRecordingIOS: true,
        playsInSilentModeIOS: true,
      });

      const { recording } = await Audio.Recording.createAsync(
        Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
      );

      setRecording(recording);
      setIsRecording(true);
    } catch (err) {
      console.error("Failed to start recording", err);
    }
  };

  const stopRecording = async () => {
    const pressDuration = Date.now() - startPressTimeRef.current; // 计算按下时间的持续时间

    setIsRecording(false);
    await recording.stopAndUnloadAsync();
    const uri = recording.getURI();
    setRecordedUri(uri);
    setRecording(null);
    alert(JSON.stringify(saveDirectory));

    if (saveDirectory) {
      const newUri = `${saveDirectory}/recording-${Date.now()}.m4a`;
      await FileSystem.copyAsync({ from: uri, to: newUri });
      alert(`Recording saved to: ${newUri}`);
      setRecordings([
        ...recordings,
        {
          uri: newUri,
          name: `Recording-${recordings.length + 1}`,
        },
      ]);
      /**
       * TODO:
       * 这里实现先保存，后删除，有点不好
       * 应该，直接将缓存视频删除，不用存，
       * 但是不知道怎么做，先这样实现
       */
      if (pressDuration < 500) {
        // 如果按下时间少于 500 毫秒，则取消录音
        setIsRecording(false);
        setRecording(null);
        alert("按下时间太短111，录音保存后，已删除");
        deleteRecording(newUri);
        return;
      }
    } else {
      alert("No directory selected, saving to default location.");
      setRecordings([
        ...recordings,
        { uri, name: `Recording ${recordings.length + 1}` },
      ]);
    }
  };

  const requestExternalStoragePermission = async () => {
    if (Platform.OS === "android") {
      try {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
          {
            title: "External Storage Permission",
            message:
              "This app needs access to your external storage to save recordings.",
            buttonNeutral: "Ask Me Later",
            buttonNegative: "Cancel",
            buttonPositive: "OK",
          }
        );
        if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
          alert("WRITE_EXTERNAL_STORAGE permission denied");
          return false;
        }
        return true;
      } catch (err) {
        console.warn(err);
        return false;
      }
    }
    return true;
  };

  const playRecording = async (uri) => {
    const soundUri = uri.startsWith("file://") ? uri : `file://${uri}`;
    const { sound } = await Audio.Sound.createAsync({ uri: soundUri });
    await sound.playAsync();
  };

  const deleteRecording = (uri) => {
    setRecordings(recordings.filter((recording) => recording.uri !== uri));
    alert("录音已删除");
  };

  const saveRecordingName = (uri) => {
    setRecordings(
      recordings.map((recording) =>
        recording.uri === uri
          ? { ...recording, name: editingName.name }
          : recording
      )
    );
    setEditingName({ uri: "", name: "" });
    setIsEditing(false);
  };

  const handlePress = (uri, name) => {
    if (singleTapRef.current) {
      clearTimeout(singleTapRef.current);
      singleTapRef.current = null;
      setIsEditing(true);
      setEditingName({ uri, name });
    }
  };

  const moveRecordingToStorage = async () => {
    const recordingUri = recordings[0]!.uri;

    const targetUri = `${
      FileSystem.documentDirectory
    }recordings/recording-${Date.now()}.3gp`;

    try {
      await FileSystem.makeDirectoryAsync(
        `${FileSystem.documentDirectory}recordings`,
        { intermediates: true }
      );

      await FileSystem.moveAsync({
        from: recordingUri,
        to: targetUri,
      });
      alert(JSON.stringify(targetUri));
      const mediaLibraryPermission =
        await MediaLibrary.requestPermissionsAsync();
      if (mediaLibraryPermission.granted) {
        const asset = await MediaLibrary.createAssetAsync(targetUri);
        const album = await MediaLibrary.getAlbumAsync("Download");
        if (album == null) {
          await MediaLibrary.createAlbumAsync("Download", asset, false);
        } else {
          await MediaLibrary.addAssetsToAlbumAsync([asset], album, false);
        }
        alert("Recording moved to storage successfully!");
      } else {
        alert("Permission to access media library is required!");
      }
    } catch (error) {
      alert("Error moving recording: " + error.message);
    }
  };

  return (
    <View
      style={{
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
      }}
    >
      <Button
        title="获取当前的外部存储权限"
        onPress={requestExternalStoragePermission}
      />
      <FlatList
        data={recordings}
        keyExtractor={(item, index) => index.toString()}
        renderItem={({ item }) => (
          <View style={styles.recordingItem}>
            <TouchableOpacity onPress={() => handlePress(item.uri, item.name)}>
              {isEditing && editingName.uri === item.uri ? (
                <TextInput
                  style={styles.recordingNameInput}
                  onChangeText={(newName) =>
                    setEditingName({ ...editingName, name: newName })
                  }
                  value={editingName.name}
                />
              ) : (
                <Text style={styles.recordingNameText}>{item.name}</Text>
              )}
            </TouchableOpacity>
            {isEditing && editingName.uri === item.uri ? (
              <Button
                title="Save"
                onPress={() => saveRecordingName(item.uri)}
              />
            ) : (
              <Button title="Play" onPress={() => playRecording(item.uri)} />
            )}
            <Button title="Delete" onPress={() => deleteRecording(item.uri)} />
          </View>
        )}
      />

      <BlurView>
        <TouchableOpacity
          style={[styles.recordButton, isRecording && styles.recording]}
          onPressIn={startRecording}
          onPressOut={stopRecording}
        >
          <Text style={styles.recordButtonText}>
            {isRecording ? "录制中..." : "按住开始录音"}
          </Text>
        </TouchableOpacity>
      </BlurView>
      <Button title="保存录音到本地存储:" onPress={moveRecordingToStorage} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flexGrow: 1,
    alignItems: "center",
    justifyContent: "center",
    padding: 20,
    backgroundColor: "#f5fcff",
  },
  title: {
    fontSize: 24,
    fontWeight: "bold",
    marginBottom: 20,
  },
  input: {
    height: 40,
    borderColor: "gray",
    borderWidth: 1,
    marginBottom: 10,
    paddingHorizontal: 10,
    width: "100%",
  },
  item: {
    padding: 10,
    fontSize: 18,
    height: 44,
  },
  editingInput: {
    height: 40,
    borderColor: "gray",
    borderWidth: 1,
    marginBottom: 10,
    paddingHorizontal: 10,
    width: "100%",
  },
  // recordButton: {
  //   backgroundColor: "#007bff",
  //   padding: 20,
  //   borderRadius: 10,
  //   marginVertical: 20,
  //   width: "80%",
  //   alignItems: "center",
  // },
  // recordButtonText: {
  //   color: "#fff",
  //   fontSize: 18,
  // },
  // recording: {
  //   backgroundColor: "red",
  // },
  recordButton: {
    backgroundColor: "#007bff",
    width: 260, // 直径 = 半径 * 2
    height: 260, // 直径 = 半径 * 2
    borderRadius: 130, // 半径
    justifyContent: "center",
    alignItems: "center",
    marginVertical: 20,
  },
  recordButtonText: {
    color: "#fff",
    fontSize: 18,
  },
  recording: {
    backgroundColor: "red",
  },
  separator: {
    marginVertical: 30,
    height: 1,
    width: "80%",
  },
  recordingItem: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    padding: 25,
    borderBottomWidth: 1,
    borderBottomColor: "#ccc",
  },
  recordingNameInput: {
    height: 40,
    borderColor: "gray",
    borderWidth: 1,
    flex: 1,
    marginRight: 10,
  },
  recordingNameText: {
    flex: 1,
    marginRight: 10,
    height: 40,
    lineHeight: 40,
  },
  playingIndicator: {
    fontSize: 14,
    color: "red",
    marginLeft: 10,
  },
  linkButton: {
    marginTop: 20,
    padding: 10,
    backgroundColor: "#28a745",
    borderRadius: 5,
  },
  linkButtonText: {
    color: "#fff",
    fontSize: 16,
  },
});
